﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

using WpfFeeCalculator.Controllers;
using WpfFeeCalculator.Model;
using WpfFeeCalculator.View;
using SpreadsheetGear;
using System.Reactive.Linq;
using WpfFeeCalculator.FeeWcfService;

namespace WpfFeeCalculator.ViewModel
{
    public class CalculationViewModel : WorkspaceViewModel
    {
        IPortfolioController _portfolioController;
        IClientController _clientController;
        IPriceCutOffController _priceCutOffController;

        Portfolio _portfolio;
        DateTime _asOfDate;
        PriceCutOff _currentPriceCutOff;

        ICommand _loadPriceCutOffCommand;
        ICommand _displayExcelDataCommand;
        ICommand _doubleClickCommand;
        ICommand _loadCalculationCommand;

        private readonly IWorkbookSet workbookSet;

        Task<DataResult> _dataResultTask;
        ObservableCollection<PriceCutOff> _priceCutOffTask;

        public ObservableCollection<CalculationViewChanges> Information { get; set; }
        private ObservableCollection<Portfolio> _portfolios { get; set; }

        private SpreadsheetGear.IWorkbook workbook;

        
        public CalculationViewModel(IPortfolioController portfolioController, IPriceCutOffController priceCutOffController, IClientController clientController)
        {
           _portfolioController = portfolioController;
           _priceCutOffController = priceCutOffController;
           _clientController = clientController;
           _asOfDate = DateTime.Today;

           
           Information = new ObservableCollection<CalculationViewChanges>();
           
           workbookSet = Factory.GetWorkbookSet();
           
           string _displayName = "Calculation View";
           base.DisplayName = _displayName;

         
        }


        //Supervising controlling pattern to allow access to non WPF spreadsheetgear control
        public ICalculationView View { get; set; }


        public ObservableCollection<Portfolio> PortfolioNames
        {
            get
            {
                if (_portfolios == null)
                {
                    _portfolios = new ObservableCollection<Portfolio>();
                    var collection = _portfolioController.GetPortfoliosAllAsync();
                    collection.Subscribe(h => 
                    { 
                        h.EventArgs.Result.ToList().ForEach(x => _portfolios.Add(x));
                        PortfoloName = _portfolios.FirstOrDefault();
                    });
                }
                return _portfolios;
            }
            set
            {
                _portfolios = value;
            }

        }

        public Portfolio PortfoloName
        {
            get { return _portfolio; }
            set
            {
                if ( value == _portfolio)
                    return;

                _portfolio = value;

                base.OnPropertyChanged("PortfoloName");
            }
        }

        public PriceCutOff CurrentPriceCutOff
        {
            get { return _currentPriceCutOff; }
            set
            {
                if (value == _currentPriceCutOff)
                    return;

                _currentPriceCutOff = value;

                base.OnPropertyChanged("CurrentPriceCutOff");
            }
        }

        public DateTime AsOfDate
        {
            get { return _asOfDate; }
            set
            {
                if (value == _asOfDate)
                    return;

                _asOfDate = value;

                base.OnPropertyChanged("AsOfDate");
            }
        }

        public Task<DataResult> UploadExcelCompleted
        {
            get { return _dataResultTask; }
            set
            {
                if (value == _dataResultTask)
                    return;
                _dataResultTask = value;
                base.OnPropertyChanged("UploadExcelCompleted");
            }
        }

        public ObservableCollection<PriceCutOff> GetPriceCutOffCompleted
        {
            get { return _priceCutOffTask; }
            set
            {
                if (value == _priceCutOffTask)
                    return;
                _priceCutOffTask = value;
            
                base.OnPropertyChanged("GetPriceCutOffCompleted");
            }
        }

        public ICommand DisplayExcelDataCommand
        {
            get
            {
                if (_displayExcelDataCommand == null)
                {
                    _displayExcelDataCommand = new RelayCommand(
                        param => this.DisplayExcelData(),
                        param => this.CanDisplayExcelData
                        );
                }
                return _displayExcelDataCommand;
            }
        }

        public void DisplayExcelData()
        {
            _clientController.ProcessDataResult(UploadExcelCompleted.Result, NotifyUser, LoadExcelDataFromStream);
        }

        bool CanDisplayExcelData
        {
            get {return UploadExcelCompleted != null && UploadExcelCompleted.IsCompleted;}
        }

        public ICommand DoubleClickCommand
        {
            get
            {
                if (_doubleClickCommand == null)
                {
                    _doubleClickCommand = new RelayCommand(
                        param => this.LoadDoubleClick(),
                        param => this.CanLoadDoubleClick
                        );
                }
                return _doubleClickCommand;
            }
        }

        public ICommand LoadPriceCutOffCommand
        {
            get
            {
                if (_loadPriceCutOffCommand == null)
                {
                    _loadPriceCutOffCommand = new RelayCommand(
                        param => this.LoadPriceCutOffs(),
                        param => this.CanLoadPriceCutOffs
                        );
                }
                return _loadPriceCutOffCommand;
            }
        }

        public ICommand LoadCalculationCommand
        {
            get
            {
                if (_loadCalculationCommand == null)
                {
                    _loadCalculationCommand = new RelayCommand(
                        param => this.LoadCalculations(),
                        param => this.CanLoadCalculations
                        );
                }
                return _loadCalculationCommand;
            }
        }
        

        bool CanLoadPriceCutOffs
        {
            get { return _portfolio != null && _portfolio.Name.Length > 0 && _asOfDate != DateTime.MinValue; }
        }

        bool CanLoadCalculations
        {
            get { return CanLoadPriceCutOffs; }
        }

        bool CanLoadDoubleClick
        {
            get {
                return Information.Any(x => true);
            }
        }

        public void LoadDoubleClick()
        {
            View.DoubleClick();
        }

        public void LoadCalculations()
        {
            var portfolioExcelTask = _clientController.GetPortfolioExcel(_portfolio, _asOfDate, _currentPriceCutOff);
            UploadExcelCompleted = portfolioExcelTask;
        }

        private void NotifyUser(string data)
        {
            View.NotifyUser(data);
        }

        private void LoadExcelDataFromStream(Stream stream)
        {
            if (workbook != null)
            {
                using (View.LockWorkBook())
                {
                    workbook.Close();
                }
            }
            using (View.LockWorkBook())
            {
                workbook = workbookSet.Workbooks.OpenFromStream(stream);
                var sheet = workbook.Worksheets["Calculations"];
                
            }
            View.SetWorkbook(workbook);
            Information.Clear();
            AddInfo(1, 2, "dddd323  23 2", 1.1m, 23.4m, null);
        }


        public void LoadPriceCutOffs()
        {
            var collection = _priceCutOffController.GetPriceCutOffsForPortfolioAsync(_portfolio.Pfo);
            if (GetPriceCutOffCompleted == null)
            {
                GetPriceCutOffCompleted = new ObservableCollection<PriceCutOff>();
                collection.Subscribe(h =>
                {
                    GetPriceCutOffCompleted.Clear();
                    h.EventArgs.Result.ToList().ForEach(x => GetPriceCutOffCompleted.Add(x));
                    CurrentPriceCutOff = GetPriceCutOffCompleted.FirstOrDefault();
                });
            }
            
        }

        private void AddInfo(int row, int column, String message, decimal? initialValue, decimal? newValue, String accepted)
        {
            Information.Add(new CalculationViewChanges() { Column = column, Row = row, Message = message, InitialValue = initialValue, NewValue = newValue, Accepted = !String.IsNullOrEmpty(accepted) });
        }
        
    }
}
